#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <stdint.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <dlfcn.h>
#include <pthread.h>
#include <linux/fb.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <syslog.h>

void handler(int sig)
{
    if(sig == SIGINT)
    {
        fprintf(stderr, "[%d]收到SIGINT\n", getpid());
        char *s = "received SIGINT";
        for(int i=0; s[i]!='\0'; i++)
        {
            fprintf(stderr, "%c", s[i]);
            usleep(100*1000);
        }
    }
    if(sig == SIGQUIT)
    {
        char *s = "catch SIGQUIT";
        for(int i=0; s[i]!='\0'; i++)
        {
            fprintf(stderr, "%c", s[i]);
            usleep(200*1000);
        }
    }   
}

int main(int argc, char const *argv[])
{
    // 信号的处理函数是会被子进程继承
    signal(SIGINT, handler);
    signal(SIGQUIT, handler);

    // 延迟响应SIGINT
    sigset_t sigs;
    sigemptyset(&sigs);
    sigaddset(&sigs, SIGINT);
    sigprocmask(SIG_BLOCK, &sigs, NULL);

    // 停留3秒，接收SIGINT
    // 在终端直接按ctrl+c，可将SIGINT同时发送给父子进程
    sleep(3);

    if(fork() == 0)
    {
        printf("PID: %d, PPID: %d\n", getpid(), getppid());

        // 解除屏蔽SIGINT，解除之后子进程不会有任何反应
        // 因为子进程不会继承父进程的挂起的信号
        sigprocmask(SIG_UNBLOCK, &sigs, NULL);

        // 如果注释掉上面的sigprocmask函函数
        // 子进程将不会响应SIGINT信号，这说明子进程会继承
        // 父进程的信号屏蔽掩码，即屏蔽了SIGINT
    }
    else
    {
        printf("PID: %d, PPID: %d\n", getpid(), getppid());

        // 解除屏蔽SIGINT，预料此处子进程不会有任何反应
        sigprocmask(SIG_UNBLOCK, &sigs, NULL);
    }

    while(1)
        pause();

    return 0;
}
